/**
 * Created by tongkx on 2015-05-55.
 */

define(function (require, exports, module) {
    var $ = require("jquery");
    var util = require("util");
    var ui = require("ui");
    //require("permission");
    require("jqtree");
    require('authorize');
    require("permission");
    var angular = require("angular");
    require("angular-interceptor");
    require("pagination");
    require("angular-ui");
    require("./roleTree");

    var api_prefix = G_CONFIG["api_prefix"];
    var api_prefix_role = api_prefix + "usermanage/role/";

    var FunctionAndRoleManager = {
        setActionSelected: function (functionActions, roleActions) {
            var func;
            for (var i = 0; func = functionActions[i]; i++) {
                if (typeof func.type == 'undefined') {
                    this.setSelectedStatus(func, roleActions);
                } else {
                    var functions;
                    if (func.functions && func.functions.length > 0) {
                        functions = func.functions;
                    } else if (func.actions && func.actions.length > 0) {
                        functions = func.actions;
                    }
                    this.setActionSelected(functions, roleActions);
                }
            }
        },
        setSelectedStatus: function (action, roleActions) {
            action.selected = false;
            if (typeof roleActions == 'undefined') {return;}
            var roleAction;
            for (var i = 0; roleAction = roleActions[i]; i++) {
                var selected = this.isActionEqual(roleAction, action);

                if (selected) {
                    action.selected = true;
                    break;
                }
            }
        },
        /**
         * 判断两个action是否相等
         * @param {{appCode:string,funcCode:string,code:string}} action
         * @param {{appCode:string,funcCode:string,code:string}} actionAnother
         * @returns {boolean}
         */
        isActionEqual: function (action, actionAnother) {
            return action.appCode === actionAnother.appCode
                && action.funcCode === actionAnother.funcCode
                && action.code === actionAnother.code;
        },
        /**
         * 移除权限
         * @param {Array.<{appCode:string,funcCode:string,code:string,name:string}>} actions
         * @param {{appCode:string,funcCode:string,code:string,name:string}} targetAction
         * @returns {boolean}
         */
        removeAction: function (actions, targetAction) {
            var action;
            for (var i = 0; action = actions[i]; i++) {
                if (this.isActionEqual(action, targetAction)) {
                    actions.splice(i, 1);
                    return true;
                }
            }
            return false;
        },
        /**
         * 移除action，以appCode
         * @param {Array.<{appCode:string,funcCode:string,code:string,name:string}>} actions
         * @param {string} appCode
         */
        removeActionByAppCode: function (actions, appCode) {
            var action;
            for (var i = 0; action = actions[i]; i++) {
                if (action.appCode === appCode) {
                    actions.splice(i, 1);
                }
            }
        }
    };

    angular
        .module("app", ["ngInterceptor", "ngUI", "roleTree"])
        .factory('httpGet', ['$http', function ($http) {
            return function (url, data) {
                if (!data) {
                    data = {};
                }
                if (!data.params) {
                    data.params = {};
                }
                data.params = $.extend(data.params, {"NEED_TOKEN": false, "USE_FORM_DATA": false});
                return $http.get(url, data);
            }
        }])
        .factory('httpPost', ['$http', function ($http) {
            return function (url, data) {
                if (!data) {
                    data = {};
                }
                data = $.extend(data, {"NEED_TOKEN": false, "USE_FORM_DATA": false});
                return $http.post(url, data);
            }
        }])
        .service("roles", ["$q", "httpGet", function ($q, httpGet) {
            return function (cache) {
                if (typeof cache === 'undefined') {
                    cache = true;
                }

                var deferred = $q.defer();
                httpGet(api_prefix_role + 'query-all-roles', {cache: cache}).success(function (res) {
                    if (res.retCode == 0) {
                        deferred.resolve(res.data);
                    }
                });
                return deferred.promise;
            }
        }])
        .service("applications", ["$q", "httpGet", function ($q, httpGet) {
            return function () {
                var deferred = $q.defer();
                httpGet(api_prefix_role + 'query-all-applications', {cache: true}).success(function (res) {
                    if (res.retCode == 0) {
                        var apps = [];

                        function invokeApp(list) {
                            var item;
                            for (var i = 0; item = list[i]; i++) {
                                var functions = item.functions;
                                if (!functions || functions.length == 0) {
                                    apps.push(item);
                                } else if (functions && functions.length > 0) {
                                    invokeApp(functions);
                                }
                            }
                        }

                        invokeApp(res.data);

                        deferred.resolve(apps);
                    }
                });
                return deferred.promise;
            }
        }])
        .service("functionActions", ["$q", "httpPost", function ($q, httpPost) {
            return function (appCodes) {
                var deferred = $q.defer();
                httpPost(api_prefix_role + 'query-function-actions', appCodes).success(function (res) {
                    if (res.retCode == 0) {
                        deferred.resolve(res.data);
                    }
                });
                return deferred.promise;
            }
        }])
        .service("roleActions", ["$q", "httpPost", function ($q, httpPost) {
            return function (ids) {
                var deferred = $q.defer();
                httpPost(api_prefix_role + 'get-roll-all-actions', ids).success(function (res) {
                    if (res.retCode == 0) {
                        deferred.resolve(res.data);
                    }
                });
                return deferred.promise;
            }
        }])
        .service("currentRole", function () {
            var lastRole;
            var curRole;
            var changeHandlers = [];

            function fire() {
                var handler;
                for (var i = 0; handler = changeHandlers[i]; i++) {
                    handler(curRole, lastRole);
                }
            }

            return {
                set: function (role) {
                    lastRole = curRole;
                    curRole = role;
                    if (lastRole !== curRole || lastRole.id !== curRole.id) {
                        fire();
                    }
                },
                get: function () {
                    return curRole;
                },
                addChangeHandler: function (handler) {
                    handler && changeHandlers.push(handler);
                },
                removeHandler: function (handler) {
                    var index = util.indexOf(handler, changeHandlers);
                    if (index > -1) {
                        changeHandlers.splice(index, 1);
                    }
                }
            };
        })
        .service("roleActionService", ['httpPost', '$q', function (httpPost, $q) {
            return {
                updateRole: function (roleId, roleActions) {
                    var deferred = $q.defer();

                    httpPost(api_prefix_role + 'update-roll-actions&roleId=' + roleId, roleActions)
                        .success(function (res) {
                            if (res.retCode == 0) {
                                deferred.resolve();
                            } else {
                                deferred.reject();
                            }
                        })
                        .error(function (res) {
                            deferred.reject();
                        });

                    return deferred.promise;
                }
            }
        }])
        .controller("RoleTreeController", ["$rootScope", "$scope", "$location", "$q", "roles", "currentRole", "httpPost", "$compile",
            function ($rootScope, $scope, $location, $q, roles, currentRole, httpPost, $compile) {
                $scope.companyRoles = [];
                $scope.groupRoles = [];

                $scope.showNewRoleDialog = function (dialogModel, dialogScope) {
                    $rootScope.$broadcast('showNewRoleDialog', dialogModel, dialogScope);
                    setTimeout(function () {
                        dialogModel.reset();
                    }, 0);
                };

                $scope.$on('newRole', function (e, roleId) {
                    getData().then(function () {
                        $tree.tree('selectNode', $tree.tree("getNodeById", roleId));
                    });
                });

                function getRole(roles, id) {
                    var role;
                    for (var i = 0; role = roles[i]; i++) {
                        if (role.id === id) {
                            break;
                        }
                    }
                    return role;
                }

                $scope.searchRole = function () {
                    getData();
                };

                $scope.showEditRoleDialog = function (id, $dialog, $dialogScope) {
                    var role = getRole($scope.companyRoles, id);

                    var type = '1';
                    if (!role) {
                        role = getRole($scope.groupRoles, id);
                        type = '0'
                    }

                    if (role) {
                        $dialogScope.data = role;
                        $dialogScope.data.type = type;
                    }
                };

                $scope.updateRole = function (id, $data, $dialog, $dialogScope) {
                    var url;

                    if ($data.type == 0) {
                        url = api_prefix_role + 'save-group-role';
                    } else {
                        url = api_prefix_role + 'save-company-role';
                    }

                    httpPost(url + '&id=' + id, {
                        name: $data.name,
                        comments: $data.comments
                    }).success(function (res) {
                        if (res.retCode == 0) {
                            $dialog.close();
                            ui.showSucTip();
                            getData();
                        }
                    })

                    return false;
                };

                /**'
                 *
                 * @param {string} keyword
                 * @param {Array} roles
                 * @returns {Array}
                 */
                function filterByRoleKeyword(keyword, roles) {
                    var res = [];
                    if (keyword) {
                        var role;
                        for (var i = 0; role = roles[i]; i++) {
                            if (role.name.indexOf(keyword) > -1) {
                                res.push(role);
                            }
                        }
                    } else {
                        res = roles;
                    }
                    return res;
                }

                var $tree = $("#tree_table")
                    .tree({
                        dragAndDrop: false,
                        useContextMenu: false,
                        autoOpen: 0, //展开级别
                        //创建节点时
                        onCreateLi: function (node, $li) {
                            if (node.parent && node.parent.parent) {
                                $li.find(".jqtree-element")
                                    .append("<div style='width:160px;' class='jqtree-btn' data-unit-id='" + node.id + "'>\
                                    <a class=' permission p-0000210201-02-inline-block' \
                                        ui-dialog='编辑角色' \
                                        ui-dialog-url='dialog/role_edit.html' \
                                        ui-dialog-cache='false' \
                                        ui-dialog-show='showEditRoleDialog(\"" + node.id + "\",$dialog,$dialogScope)' \
                                        ui-dialog-ok='updateRole(\"" + node.id + "\",$data,$dialog,$dialogScope)'\
                                     style='margin-left:5px;'><i class='icon-op-edit' data-trigger='edit'>&nbsp;</i></a>\
                                    <a class=' permission p-0000210201-03-inline-block' style='margin-left:5px;'><i class='icon-op-del' data-trigger='dele'>&nbsp;</i></a>\
                                </div>");
                            }
                        },
                        onCanMove: function (node) {
                            return false;
                        },
                        onCanMoveTo: function (moved_node, target_node, position) {
                            return false;
                        },
                        onIsMoveHandle: function ($ele) {
                            return false;
                        },
                        onCanSelectNode: function (node) {
                            if (node.children.length == 0) {
                                return true;
                            } else {
                                return false;
                            }
                        }
                    })
                    .on('tree.select', function (e) {
                        var node = e.node;
                        if (node) {
                            currentRole.set({
                                id: node.id,
                                name: node.name,
                                comments: node.comments
                            });
                        }
                    })
                    .on('tree.click', function (e) {
                        var node = e.node;
                        var trigger = $(e.click_event.target).attr('data-trigger');
                        if (trigger) {
                            switch (trigger) {
                                case 'edit':
                                    e.preventDefault();
                                    break;
                                case 'dele':
                                    e.preventDefault();

                                    var roleId = node.id;
                                    util.confirm('确定删除角色吗？', {
                                        ok: function () {
                                            httpPost(api_prefix_role + 'delete-role&roleId=' + roleId)
                                                .success(function (res) {
                                                    if (res.retCode == 0) {
                                                        var node = $tree.tree('getNodeById', roleId);
                                                        $tree.tree('removeNode', node);

                                                        var curRole = currentRole.get();
                                                        if (curRole && curRole.id === roleId) {
                                                            currentRole.set(null);
                                                        }

                                                        ui.showSucTip();
                                                    }
                                                });
                                        }
                                    });
                                    break;
                            }
                        }
                    })

                function getData() {
                    return roles(false).then(function (rolesData) {
                        var companyRoles = $scope.companyRoles = filterByRoleKeyword($scope.keyword, rolesData['companyRoles']);
                        var groupRoles = $scope.groupRoles = filterByRoleKeyword($scope.keyword, rolesData['groupRoles']);

                        $tree.tree('loadData', [
                            {
                                id: 'groupRoles',
                                name: '集团级角色',
                                children: groupRoles
                            },
                            {
                                id: 'companyRoles',
                                name: '公司级角色',
                                children: companyRoles
                            }
                        ]);

                        $compile($tree)($scope);
                        if(rolesData&&rolesData.groupRoles&&rolesData.groupRoles.length>0){
                            $scope.currentSelectedRole = rolesData.groupRoles[0].id;
                            $tree.tree('selectNode', $tree.tree("getNodeById", $scope.currentSelectedRole));
                        }
                    });
                }

                getData();
            }])
        .controller("FunctionController", ["$scope", "$q", "currentRole", "applications", "roleActions", "functionActions", "httpPost", "roles", "roleActionService",
            function ($scope, $q, currentRole, applications, roleActions, functionActions, httpPost, roles, roleActionService) {
                /**
                 * 获取选中的授权模块
                 * @returns {Array}
                 */
                function getSelectedApps() {
                    var res = [];
                    var app;
                    for (var i = 0; app = $scope.apps[i]; i++) {
                        if (app.selected) {
                            res.push(app);
                        }
                    }
                    return res;
                }

                /**
                 * @param {string} appCode
                 */
                var doSetTabAppSelected = function (appCode) {
                    $scope.selectedTabAppCode = appCode;
                    functionActions([appCode]).then(function (funcs) {
                        FunctionAndRoleManager.setActionSelected(funcs, $scope.roleActions);
                        $scope.functionActions = funcs;
                        angular.forEach(funcs, function (func) {
                            //只需要设置第一层的selected状态
                            angular.forEach(func.functions, function (func) {
                                updateActionGroupSelected(func);
                            });
                        });
                    });
                };

                function setAppSelect(app) {
                    //if(!$scope.functionActions || $scope.functionActions.length==0){return;}
                    $scope.selectedAppCode = app.appCode;
                    if (app.selected) {
                        $scope.selectedApps = getSelectedApps();

                        if ((!$scope.selectedTabAppCode && $scope.selectedApps.length > 0) ||
                            (!app.selected && app.appCode === $scope.selectedTabAppCode)) {
                            doSetTabAppSelected($scope.selectedApps[0].appCode);
                        }
                    } else {
                        var index = util.indexOf(app, $scope.selectedApps);
                        if (index > -1) {
                            $scope.selectedApps.splice(index, 1);
                        }

                        if ($scope.selectedApps.length == 0) {
                            $scope.functionActions = [];
                            $scope.selectedTabAppCode = null;
                        } else {
                            if ($scope.selectedTabAppCode == app.appCode) {
                                doSetTabAppSelected($scope.selectedApps[0].appCode);
                            }
                        }
                    }
                }

                $scope.selectedTabAppCode = null;
                $scope.selectedApps = [];
                $scope.setAppSelect = setAppSelect;
                applications().then(function (apps) {
                    $scope.apps = apps;
                });

                roles().then(function (rolesData) {
                    $scope.roles = rolesData;
                });

                /**
                 * 切换角色
                 * @param {string} roleId
                 */
                function switchRole(roleId) {
                    if (roleId) {
                        $scope.currentSelectedRole = roleId;
                        $scope.selectedTabAppCode = null;
                        $q.when(roleActions([roleId])).then(function (res) {
                            var roleActions = res;
                            var appCodes = _.uniq(_.pluck(roleActions, 'appCode'));
                            var apps = _.filter($scope.apps, function (app) {
                                if (!(_.indexOf(appCodes, app.appCode) < 0)) {
                                    app.selected = true;
                                    //$scope.setAppSelect(app);
                                    return true
                                } else {
                                    app.selected = false;
                                    //$scope.setAppSelect(app);
                                }
                            })
                            $scope.roleActions = roleActions;
                            $scope.selectedApps = apps;
                            return appCodes;
                        }).then(function (res) {
                            $q.when(functionActions(res)).then(function (functionActions) {
                                var apps = _.each($scope.selectedApps, function (app) {
                                    $scope.setAppSelect(app);
                                });
                                if(functionActions.length<1){
                                    $scope.functionActions = functionActions;
                                }
                            })
                        });
                    }
                }
                $scope.updateAction = function (action, func) {
                    var roleActions = $scope.roleActions;
                    updateAction(roleActions, action);
                    updateActionGroupSelected(func);
                };
                $scope.updateActionGroup = function (func) {
                    var selected = func.selected;
                    var roleActions = $scope.roleActions;
                    updateChildActions(func);
                    function updateChildActions(func) {
                        angular.forEach(func.actions, function (item) {
                            if (item.selected != selected) {
                                item.selected = selected;
                                updateAction(roleActions, item);
                            }
                        });
                        angular.forEach(func.functions, updateChildActions);
                    }
                };
                function updateAction(roleActions, action) {
                    if (action.selected) {
                        roleActions.push(action);
                    } else {
                        FunctionAndRoleManager.removeAction(roleActions, action);
                    }
                }

                function updateActionGroupSelected(func) {
                    func.selected = isActionAllSelect(func);
                }

                function isActionAllSelect(func) {
                    var selAll = true;
                    for (var i = 0; i < func.actions.length; i++) {
                        selAll = selAll && func.actions[i].selected;
                        if (!selAll)break;
                    }
                    if (selAll) {
                        for (var i = 0; i < func.functions.length; i++) {
                            selAll = isActionAllSelect(func.functions[i]);
                            if (!selAll)break;
                        }
                    }
                    return selAll;
                }

                $scope.setTabAppSelected = function (app) {
                    doSetTabAppSelected(app.appCode);
                };
                $scope.updateRole = function () {
                    var roleActions = $scope.roleActions;
                    var postData = [];
                    var item;
                    for (var i = 0; item = roleActions[i]; i++) {
                        postData.push(item);
                    }

                    roleActionService.updateRole(currentRole.get().id, roleActions).then(function () {
                        ui.showSucTip();
                    });
                };

                $scope.copyRoles = function (selectes) {
                    switchRole(selectes[0]);
                };

                currentRole.addChangeHandler(function (curRole, lastRole) {
                    if (curRole) {
                        switchRole(curRole.id);
                    } else {
                        $scope.functionActions = null;
                        $scope.roleActions = null;
                    }
                });
            }])
        .controller("RoleController", ["$rootScope", "$scope", "applications", "functionActions", "httpPost", "roleActionService", "roles", "roleActions",
            function ($rootScope, $scope, applications, functionActions, httpPost, roleActionService, roles, roleActions) {
                var dialog;
                var dialogScope;
                var selectedActions = [];

                $scope.$on('showNewRoleDialog', function (e, dialogModel, dialogScope1) {
                    dialogModel.button([]);
                    dialog = dialogModel;
                    dialogScope = dialogScope1;
                });

                $scope.showIndex = 0;

                $scope.roleInfo = {
                    roleName: '',
                    roleType: 0,
                    roleDesc: ''
                };

                $scope.selectedApps = [];

                applications().then(function (apps) {
                    $scope.apps = apps;
                });
                roles().then(function (rolesData) {
                    $scope.roles = rolesData;
                });

                $scope.setFormScope = function (scope) {
                    $scope.formScope = scope;
                };

                /**
                 * 获取选中的授权模块
                 * @returns {Array}
                 */
                function getSelectedApps() {
                    var res = [];
                    var app;
                    for (var i = 0; app = $scope.apps[i]; i++) {
                        if (app.selected) {
                            res.push(app);
                        }
                    }
                    return res;
                }

                $scope.setAppSelect = function (app) {
                    if (app.selected) {
                        $scope.selectedApps = getSelectedApps();

                        if ((!$scope.selectedTabAppCode && $scope.selectedApps.length > 0) ||
                            (!app.selected && app.appCode === $scope.selectedTabAppCode)) {
                            doSetTabAppSelected($scope.selectedApps[0].appCode);
                        }
                    } else {
                        var index = util.indexOf(app, $scope.selectedApps);
                        if (index > -1) {
                            $scope.selectedApps.splice(index, 1);
                        }

                        if ($scope.selectedApps.length == 0) {
                            $scope.functionActions = [];
                            $scope.selectedTabAppCode = null;
                        } else {
                            if ($scope.selectedTabAppCode == app.appCode) {
                                doSetTabAppSelected($scope.selectedApps[0].appCode);
                            }
                        }

                        FunctionAndRoleManager.removeActionByAppCode(selectedActions, app.appCode);
                    }
                };

                $scope.updateAction = function (action, func) {
                    updateAction(selectedActions, action);
                    updateActionGroupSelected(func);
                };
                $scope.updateActionGroup = function (func) {
                    var selected = func.selected;
                    var roleActions = selectedActions;
                    updateChildActions(func);
                    function updateChildActions(func) {
                        angular.forEach(func.actions, function (item) {
                            if (item.selected != selected) {
                                item.selected = selected;
                                updateAction(roleActions, item);
                            }
                        });
                        angular.forEach(func.functions, updateChildActions);
                    }
                };
                function updateAction(roleActions, action) {
                    if (action.selected) {
                        roleActions.push(action);
                    } else {
                        FunctionAndRoleManager.removeAction(roleActions, action);
                    }
                }

                function updateActionGroupSelected(func) {
                    func.selected = isActionAllSelect(func);
                }

                function isActionAllSelect(func) {
                    var selAll = true;
                    for (var i = 0; i < func.actions.length; i++) {
                        selAll = selAll && func.actions[i].selected;
                        if (!selAll)break;
                    }
                    if (selAll) {
                        for (var i = 0; i < func.functions.length; i++) {
                            selAll = isActionAllSelect(func.functions[i]);
                            if (!selAll)break;
                        }
                    }
                    return selAll;
                }

                /**
                 * 一键授权
                 * @param selects
                 */
                $scope.copyRoles = function (selects) {
                    roleActions([selects[0]]).then(function (roleActions) {
                        selectedActions = roleActions;

                        var appCodes = {};
                        var item;
                        for (var i = 0; item = selectedActions[i]; i++) {
                            appCodes[item.appCode] = true;
                        }

                        var apps = $scope.apps;
                        var app;
                        for (var i = 0; app = apps[i]; i++) {
                            if (appCodes[app.appCode]) {
                                app.selected = true;
                            } else {
                                app.selected = false;
                            }
                        }

                        $scope.selectedApps = getSelectedApps();

                        if ($scope.selectedApps.length > 0) {
                            doSetTabAppSelected($scope.selectedApps[0].appCode);
                        }

                        if ($scope.functionActions && $scope.functionActions.length > 0) {
                            FunctionAndRoleManager.setActionSelected($scope.functionActions, selectedActions);
                        }
                    });
                };

                $scope.selectedTabAppCode = null;

                /**
                 * @param {string} appCode
                 */
                var doSetTabAppSelected = function (appCode) {
                    $scope.selectedTabAppCode = appCode;
                    functionActions([appCode]).then(function (funcs) {
                        FunctionAndRoleManager.setActionSelected(funcs, selectedActions);
                        $scope.functionActions = funcs;
                        angular.forEach(funcs, function (func) {
                            //只需要设置第一层的selected状态
                            angular.forEach(func.functions, function (func) {
                                updateActionGroupSelected(func);
                            });
                        });
                    });
                };

                $scope.setTabAppSelected = function (app) {
                    doSetTabAppSelected(app.appCode);
                };

                $scope.next = function () {
                    var roleEditForm = $scope.formScope.role_add_form;
                    roleEditForm.$setSubmitted(true);
                    if (roleEditForm.$invalid) {
                        return;
                    }

                    $scope.showIndex += 1;

                    setTimeout(function () {
                        dialog.reset();
                    }, 0);
                };
                $scope.pre = function () {
                    $scope.showIndex -= 1;

                    setTimeout(function () {
                        dialog.reset();
                    }, 0);
                };

                $scope.save = function () {
                    var url;

                    var roleInfo = $scope.roleInfo;
                    if (roleInfo.roleType == 0) {
                        url = api_prefix_role + 'save-group-role';
                    } else {
                        url = api_prefix_role + 'save-company-role';
                    }

                    httpPost(url, {name: roleInfo.roleName, comments: roleInfo.roleDesc}).success(function (res) {
                        if (res.retCode == 0) {
                            var roleId = res.data;
                            roleActionService.updateRole(roleId, selectedActions)
                                .then(function () {
                                    $rootScope.$broadcast('newRole', roleId);
                                    dialog.close();
                                    ui.showSucTip();
                                });
                        }
                    })
                };

                $scope.cancel = function () {
                    dialog.close();
                };
            }])


    angular.bootstrap(document, ['app']);
});